#ifndef __OC_Model_H__
#define __OC_Model_H__

#include "OCMain/Quaternion.h"
#include "MeshBuilder.h"
#include "shaderClass.h"
#include "Texture.h"
#include "Camera.h"
#include "State.h"
#include "ShadowMapFrameBuffer.h"

namespace OCPP
{
	class _openGLExport ModelTransform
	{
	public:
		ModelTransform() {}
		~ModelTransform() {}

		void setMatrix(Matrix4 m)
		{
			mModelMatrix = m;
			mbDirty = false;
		}
		void setPosition(Vector3 position)
		{
			mPosition = position;
			mbDirty = true;
		}

		void setScale(Vector3 scale)
		{
			mScale = scale;
			mbDirty = true;
		}

		void setQuaternion(Quaternion quaternion)
		{
			mQuaternion = quaternion;
			mbDirty = true;
		}

		const Matrix4& getModelMatrix()
		{
			if (mbDirty)
			{
				mbDirty = false;
				mModelMatrix.makeTransform(mPosition, mScale, mQuaternion);
			}
			return mModelMatrix;
		}
	protected:
		bool		mbDirty = false;
		Vector3		mPosition = Vector3::ZERO;
		Vector3		mScale = Vector3::UNIT_SCALE;
		Quaternion	mQuaternion = Quaternion::IDENTITY;
		Matrix4		mModelMatrix = Matrix4::IDENTITY;
	};

	class _openGLExport Model : public ModelTransform
	{
	public:
		Model();
		~Model();
		void setInstanceMatrix(Matrix4List instanceMatrixs);
		void loadShader(String vsFileName, String fsFileName, String geomFile);
		void loadOutlineShader(String vsFileName, String fsFileName);
		void loadShadowShader(String vsFileName, String fsFileName);
		void load(String fileName);
		void setMeshList(MeshList meshes) { mMeshList = meshes; }
		void addMesh(MeshPtr mesh) { mMeshList.push_back(mesh); }

		void draw(Camera& camera, State& shaderState,Shader& shader);
		void draw(Camera& camera, State& shaderState);
		void drawShadow(Camera& camera, State& shaderState);

		void setOutlineWidth(int width) { mOutlineWidth = width; }

		Shader* getShader() { return &mShader; }
	private:
		Matrix4List		mInstanceMatrixs;
		Vector3List		mVertices;
		Vector3List		mNormals;
		Vector3List		mColors;
		Vector2List		mTextureCoords;
		IndiceList		mIndices;
		Shader			mShader;
		Shader			mOutlineShader;
		Shader			mShadowShader;
		ShadowMapFrameBuffer*	mShadowMapFrameBuffer;
		std::vector<std::shared_ptr<Texture> > mTextureList;
		bool			mbLoaded = false;
		int mOutlineWidth = 0;
		MeshList mMeshList;
	};
}

#endif // !__OC_WINDOW_H__
